#include "expandpane.h"
#include "gui.h"

extern HINSTANCE g_hInst;
extern HFONT hfontSegoe;

static HWND ExpandPanes[16];
static int TotalPanes = 0;

#define EXPAND_PANE_BASE_ID	1137
static int ID = EXPAND_PANE_BASE_ID;

static int expand_pane_selection = -1;

typedef struct {
	BOOL bExpanded, bButtonHot, bHot;
	HWND contents;
	HWND hwndBtn;
	DWORD dwHeight;
} expand_pane_settings, ep_settings;

HWND CreateExpandPane(HWND hwndParent, char *name, HWND contents) {
	
	expand_pane_settings *eps = malloc(sizeof(expand_pane_settings));
	memset(eps, 0, sizeof(expand_pane_settings));
	
	eps->bExpanded = TRUE;
	eps->contents = contents;
	
	if (ID == EXPAND_PANE_BASE_ID) {
		TotalPanes = 0;
	}
	
	HWND hwndExp = CreateWindow(
			g_szExpandPane,
			name,
			WS_VISIBLE | WS_CHILD,
			0, 0, 1, 1,
			hwndParent, (HMENU) ID++, g_hInst,
			eps
			);
	if (hwndExp == NULL)
		return NULL;
	
	TEXTMETRIC tm;
	GetTextMetrics(GetDC(hwndExp), &tm);
	
	if (contents != NULL) {
		if (SetParent(contents, hwndExp) == NULL)
		{
			MessageBox(NULL, "Unable to set parent!\n", "shit", MB_OK);
		}
		ShowWindow(contents, SW_SHOW);
		SetWindowPos(contents, NULL, 16, tm.tmHeight*3/2, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
	}
		
	ExpandPanes[TotalPanes++] = hwndExp;
	
	return hwndExp;
}

void ArrangeExpandPanes(void) {
	int i;
	for (i = 0; i < TotalPanes; i++) {
		SendMessage(ExpandPanes[i], WM_SIZE, 0, 0);
	}
	
}

void GetExpandPaneState(ep_state *state) {
	state->total = TotalPanes;
	
	int i;
	for (i = 0; i < TotalPanes; i++)
	{
		ep_settings *eps = (ep_settings*) GetWindowLong(ExpandPanes[i], GWL_USERDATA);
		state->state[i] = eps->bExpanded;
	}
	
	ArrangeExpandPanes();
}

void SetExpandPaneState(const ep_state *state) {
	int i;
	for (i = 0; i < TotalPanes; i++) {
		ep_settings *eps = (ep_settings*) GetWindowLong(ExpandPanes[i], GWL_USERDATA);
		eps->bExpanded = state->state[i];
	}
	
}

void DrawHeader(HDC hdc, char *s, int y, int width) {
	
	SelectObject(hdc, hfontSegoe);
	
	TEXTMETRIC tm;
	GetTextMetrics(hdc, &tm);
	
	RECT r = {8, y, width, y + tm.tmHeight*3/2};

	SetBkMode(hdc, TRANSPARENT);
	SetTextColor(hdc, RGB(0, 51, 153));
	DrawTextEx(hdc, s, -1, &r, DT_LEFT | DT_VCENTER | DT_SINGLELINE, NULL);
	
	DrawTextEx(hdc, s, -1, &r, DT_LEFT | DT_CALCRECT | DT_VCENTER | DT_SINGLELINE, NULL);
	SelectObject(hdc, GetStockObject(DC_PEN));
	SetDCPenColor(hdc, RGB(176, 191, 222));
	MoveToEx(hdc, r.right + tm.tmAveCharWidth/2, (r.bottom - r.top)/2 + 1, NULL);
	LineTo(hdc, width - 28, (r.bottom - r.top)/2 + 1);
}

static WNDPROC OldButtonProc;
static HDC hdcButtons = NULL;

LRESULT CALLBACK ExpandButtonProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {

	switch (Message) {
		case WM_MOUSEMOVE: {
			ep_settings *eps = (ep_settings*) GetWindowLong(hwnd, GWL_USERDATA);
			
			if (eps->bButtonHot == FALSE) {
				eps->bButtonHot = TRUE;
				
				InvalidateRect(hwnd, NULL, TRUE);
				UpdateWindow(hwnd);
				
				TRACKMOUSEEVENT tme;
				tme.cbSize = sizeof(tme);
				tme.dwFlags = TME_LEAVE;
				tme.hwndTrack = hwnd;
				tme.dwHoverTime = 1;
				TrackMouseEvent(&tme);
			}
			
			return 0;
		}
		case WM_MOUSELEAVE: {
			ep_settings *eps = (ep_settings*) GetWindowLong(hwnd, GWL_USERDATA);

			eps->bButtonHot = FALSE;

			InvalidateRect(GetParent(hwnd), NULL, TRUE);
			return 0;
		}
		case WM_PAINT: {
			ep_settings *eps = (ep_settings*) GetWindowLong(hwnd, GWL_USERDATA);
			
			if (hdcButtons == NULL) {
				HBITMAP hbmButtons = LoadBitmap(g_hInst, "expandpanebuttons");
				hdcButtons = CreateCompatibleDC(GetDC(hwnd));
				SelectObject(hdcButtons, hbmButtons);
			}
			
			HDC hdc;
			PAINTSTRUCT ps;
			
			hdc = BeginPaint(hwnd, &ps);
			int base_x = 0;
			if (eps->bExpanded)
				base_x = 30;
				
			if (eps->bButtonHot)
				base_x += 15;
				
			RECT rc;
			GetClientRect(hwnd, &rc);
			
			BitBlt(hdc, (rc.right - rc.left - 15)/2,
					(rc.bottom - rc.top - 15)/2, 15, 15, hdcButtons, base_x, 15, SRCAND);

			BitBlt(hdc, (rc.right - rc.left - 15)/2, 
					(rc.bottom - rc.top - 15)/2, 15, 15, hdcButtons, base_x, 0, SRCPAINT);
			
			EndPaint(hwnd, &ps);
			return 0;
		}
		default:
			return CallWindowProc(OldButtonProc, hwnd, Message, wParam, lParam);
	}
	
	
}

LRESULT CALLBACK ExpandPaneProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
	static TEXTMETRIC tm;
	
	switch (Message) {
		case WM_CREATE:
		{
			expand_pane_settings *eps;
			
			eps = ((CREATESTRUCT*)lParam)->lpCreateParams;
			SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) eps);
			
			eps->hwndBtn = CreateWindowEx(
					WS_EX_TRANSPARENT,	// this lets the other shit behind it get drawn first
					"BUTTON",
					"V",
					BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE,
					0, 0, 1, 1,
	                hwnd, (HMENU) 1500, g_hInst, NULL); 
			
			eps->bButtonHot = FALSE;
			eps->bHot = FALSE;
			eps->bExpanded = FALSE;
			
			OldButtonProc = GetWindowLong(eps->hwndBtn, GWL_WNDPROC);
			SetWindowLong(eps->hwndBtn, GWL_WNDPROC, (LONG) ExpandButtonProc);
			SetWindowLong(eps->hwndBtn, GWL_USERDATA, eps);
			
			GetTextMetrics(GetDC(hwnd), &tm);
			eps->dwHeight = 100;
			return 0;
		}
		case WM_MOUSEMOVE: {
			ep_settings *eps = (ep_settings*) GetWindowLong(hwnd, GWL_USERDATA);
			
			if (GET_Y_LPARAM(lParam) < tm.tmHeight*3/2) {
				if (eps->bHot == FALSE) {
					eps->bHot = TRUE;
					
					InvalidateRect(hwnd, NULL, TRUE);
					UpdateWindow(hwnd);
					
					TRACKMOUSEEVENT tme;
					tme.cbSize = sizeof(tme);
					tme.dwFlags = TME_LEAVE;
					tme.hwndTrack = hwnd;
					tme.dwHoverTime = 1;
					TrackMouseEvent(&tme);
				}
				return 0;
			}
			// Fall through to mouseleave
		}
		case WM_MOUSELEAVE: {
			ep_settings *eps = (ep_settings*) GetWindowLong(hwnd, GWL_USERDATA);

			eps->bHot = FALSE;

			InvalidateRect(hwnd, NULL, TRUE);
			UpdateWindow(hwnd);
			return 0;
		}
		case WM_SIZE:
		{
			ep_settings *eps = (ep_settings*) GetWindowLong(hwnd, GWL_USERDATA);
			
			HDC hdc = GetDC(hwnd);
			SelectObject(hdc, hfontSegoe);
			
			ReleaseDC(hwnd, hdc);
			
			RECT prc;
			GetWindowRect(GetParent(hwnd), &prc);
			
			DWORD dwHeight = tm.tmHeight*3/2;
			DWORD dwWidth = prc.right - prc.left;
			int index = GetWindowLong(hwnd, GWL_ID) - EXPAND_PANE_BASE_ID;

			int cy = 2;
			int i;
			for (i = 0; i < index; i++) {
				RECT rc;
				GetWindowRect(ExpandPanes[i], &rc);
				//printf("windowrect: %ld %ld %ld %ld\n", rc.left, rc.top ,rc.right, rc.bottom);
				cy += rc.bottom - rc.top;
			}
			
			if (eps->contents) {
				SendMessage(eps->contents, WM_SIZE, 0, 0);
				
				WINDOWINFO wi;
				GetWindowInfo(eps->contents, &wi);
				
				eps->dwHeight = wi.rcClient.bottom - wi.rcClient.top;
			}
			
			if (eps->bExpanded)
				dwHeight = eps->dwHeight;
				
			SetWindowPos(hwnd, NULL, 2, cy, dwWidth - 4, dwHeight, SWP_NOZORDER);
			SetWindowPos(eps->hwndBtn, NULL, dwWidth - 24 - 8, (tm.tmHeight*3/2 - 20)/2, 20, 20, SWP_NOZORDER);
			
			if (eps->contents) {
				//SetWindowPos(eps->contents, NULL, 16, tm.tmHeight*3/2, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
			}
			
			InvalidateRect(hwnd, NULL, TRUE);
			UpdateWindow(hwnd);

			return 0;
		}
		case WM_PAINT:
		{
			ep_settings *eps = (ep_settings*) GetWindowLong(hwnd, GWL_USERDATA);
			
			PAINTSTRUCT ps;
			HDC hdc;
			
			hdc = BeginPaint(hwnd, &ps);
			
			RECT rc;
			GetClientRect(hwnd, &rc);
			
			RECT r;
			CopyRect(&r, &rc);
			r.bottom = r.top + tm.tmHeight*3/2;
			
			FillRect(hdc, &r, GetStockObject(WHITE_BRUSH));
			if (eps->bHot) {
				DrawItemSelection(hdc, &r, TRUE, 130);
			}
			
			CopyRect(&r, &rc);
			r.top += tm.tmHeight*3/2;
			r.right = 16;
			FillRect(hdc, &r, GetStockObject(WHITE_BRUSH));
			
			RECT rContents;
			GetClientRect(eps->contents, &rContents);
			CopyRect(&r, &rc);
			r.left = rContents.right;
			r.top += tm.tmHeight*3/2;
			FillRect(hdc, &r, GetStockObject(WHITE_BRUSH));
			
			TCHAR pszText[32];
			GetWindowText(hwnd, pszText, sizeof(pszText));
			
			DrawHeader(hdc, pszText, 0, rc.right - rc.left);
			
			
			EndPaint(hwnd, &ps);
			return 0;
		}
		case WM_COMMAND: {
			ep_settings *eps = (ep_settings*) GetWindowLong(hwnd, GWL_USERDATA);
			switch (HIWORD(wParam)) {
				case BN_CLICKED:
				{
					eps->bExpanded = eps->bExpanded == TRUE ? FALSE : TRUE;
					
					RECT rc;
					GetClientRect(hwnd, &rc);
					
					InvalidateRect(hwnd, NULL, TRUE);
					ArrangeExpandPanes();
					InvalidateRect(GetParent(hwnd), NULL, TRUE);
					return 0;
				}
			}
		}
		case WM_DESTROY: {
			ID--;
		}
		default:
			return DefWindowProc(hwnd, Message, wParam, lParam);
	}
	return 0;
}
